﻿//-------------------------------------------------------------------
//	Copyright (c) 2010-2014  Zhirnov Andrey
//	This file is part of the "UX Standard Lib" project.
//	See copyright notice in "UX_STL_Ext.h".
//-------------------------------------------------------------------

#ifndef _UXS_AL_SOUND_SYSTEM_H
#define _UXS_AL_SOUND_SYSTEM_H

#pragma once

#include "ALSound.h"

namespace UX_STL
{
namespace ALShell
{

	//
	// Sound System
	//

	class UX_EXPORT ALSoundSystem : public ALBaseObject
	{
	private:
		ALCcontext	 *		_pContext;
		ALCdevice	 *		_pDevice;
		uint				_uMaxAuxSends;
		uint				_uEfxVersion;
		bool				_bPause;

	public:
		ALSoundSystem();
		~ALSoundSystem();
		
		bool Init(uni_c_string pAudioDevice = uni_c_string(), uint uAUXSlots = 0);
		void GetOpenALInfo(string &sInfo) const;

		void MakeCurrent()	const;

		void Pause();
		void Resume();

		void SetListenerPosition(const fvec3 &sPos) const;
		void SetListenerVelocity(const fvec3 &sVel) const;
		void SetListenerVolume(float fVolume) const;
		void SetListenerOrientation(const fvec3 &sForward, const fvec3 &sUp) const;
		void SetDistanceModel(al_distance_model::type eType);
		void SetDopplerFactor(float fValue) const;
		void SetDopplerVelocity(float fValue) const;
		void SetSpeedOfSound(float fValue) const;

		void GetListenerOrientation(fvec3 &sForward, fvec3 &sUp) const;
		fvec3 const				GetListenerPosition() const;
		float					GetListenerVolume() const;
		al_distance_model::type	GetDistanceModel() const;
		float					GetDopplerFactor() const;
		float					GetDopplerVelocity() const;
		float					GetSpeedOfSound() const;

		
		bool		IsContextPaused()	const	{ return _bPause; }
		uint		MaxAuxSends()		const	{ return _uMaxAuxSends; }
		uint		GetEfxVersion()		const	{ return _uEfxVersion; }

		ALCdevice *	GetDevice()			const	{ return _pDevice; }
		ALCcontext*	GetContext()		const	{ return _pContext; }
	};

/*
=================================================
	установить текущий контекст
=================================================
*/
	inline void ALSoundSystem::MakeCurrent() const
	{
		if ( _pContext != alcGetCurrentContext() )
			alcMakeContextCurrent( _pContext );
	}
	
/*
=================================================
	установить позицию слушателя
=================================================
*/
	inline void ALSoundSystem::SetListenerPosition(const fvec3 &vPos) const
	{
		AL_CALL( alListenerfv( AL_POSITION, (const ALfloat *)vPos.ptr() ) );
	}
	
/*
=================================================
	установить скорость слушателя
=================================================
*/
	inline void ALSoundSystem::SetListenerVelocity(const fvec3 &vVel) const
	{
		AL_CALL( alListenerfv( AL_VELOCITY, (const ALfloat *)vVel.ptr() ) );
	}
	
/*
=================================================
	установить громкость
=================================================
*/
	inline void ALSoundSystem::SetListenerVolume(float fVolume) const
	{
		AL_CALL( alListenerf( AL_GAIN, fVolume ) );
	}
	
/*
=================================================
	установить направление слушателя
=================================================
*/
	inline void ALSoundSystem::SetListenerOrientation(const fvec3 &sForward, const fvec3 &sUp) const
	{
		const float a_orient[6] = { sForward.x, sForward.y, sForward.z, sUp.x, sUp.y, sUp.z };

		AL_CALL( alListenerfv( AL_ORIENTATION, a_orient ) );
	}
	
/*
=================================================
	устоновить модель рассчета громкости звука
	в зависимости от расстояния
=================================================
*/
	inline void ALSoundSystem::SetDistanceModel(al_distance_model::type eType)
	{
		AL_CALL( alDistanceModel( eType ) );
	}
	
/*
=================================================
	установить коэффициент для расчета эффекта Допплера,
	0 - отключить эффект
=================================================
*/
	inline void ALSoundSystem::SetDopplerFactor(float fValue) const
	{
		AL_CALL( alDopplerFactor( fValue ) );
	}
	
/*
=================================================
	установить коэффициент для скорости звука
=================================================
*/
	inline void ALSoundSystem::SetDopplerVelocity(float fValue) const
	{
		AL_CALL( alDopplerVelocity( fValue ) );
	}
	
/*
=================================================
	установить скорость звука
=================================================
*/
	inline void ALSoundSystem::SetSpeedOfSound(float fValue) const
	{
		AL_CALL( alSpeedOfSound( fValue ) );
	}

/*
=================================================
	возвращает направление слушателя
=================================================
*/
	inline void ALSoundSystem::GetListenerOrientation(fvec3 &sForward, fvec3 &sUp) const
	{
		ALfloat a_orient[6] = {0};

		AL_CALL( alGetListenerfv( AL_ORIENTATION, a_orient ) );
		sForward = fvec3( a_orient );
		sUp		 = fvec3( a_orient + 3 );
	}
	
/*
=================================================
	возвращает позицию слушателя
=================================================
*/
	inline fvec3 const ALSoundSystem::GetListenerPosition() const
	{
		fvec3	ret;
		AL_CALL( alGetListenerfv( AL_POSITION, (ALfloat *)ret.ptr() ) );
		return ret;
	}
	
/*
=================================================
	возвращает громкость звука
=================================================
*/
	inline float ALSoundSystem::GetListenerVolume() const
	{
		float	f_gain;
		AL_CALL( alGetListenerf( AL_GAIN, &f_gain ) );
		return f_gain;
	}
	
/*
=================================================
	возвращает модель расчета звука
=================================================
*/
	inline al_distance_model::type ALSoundSystem::GetDistanceModel() const
	{
		ALint	ret = 0;
		AL_CALL( ret = alGetInteger( AL_DISTANCE_MODEL ) );
		return al_distance_model::type( ret );
	}
	
/*
=================================================
	возвращает коэффициент для расчета эффекта Допплера
=================================================
*/
	inline float ALSoundSystem::GetDopplerFactor() const
	{
		float	ret = 0.f;
		AL_CALL( ret = alGetFloat( AL_DOPPLER_FACTOR ) );
		return ret;
	}
	
/*
=================================================
	возвращает коэффициент для скорости звука
=================================================
*/
	inline float ALSoundSystem::GetDopplerVelocity() const
	{
		float	ret = 0.f;
		AL_CALL( ret = alGetFloat( AL_DOPPLER_VELOCITY ) );
		return ret;
	}
	
/*
=================================================
	возвращает скорость звука
=================================================
*/
	inline float ALSoundSystem::GetSpeedOfSound() const
	{
		float	ret = 0.f;
		AL_CALL( ret = alGetFloat( AL_SPEED_OF_SOUND ) );
		return ret;
	}
	
/*
=================================================
	приостановить/запустить контекст
=================================================
*/
	inline void ALSoundSystem::Pause()
	{
		if ( _bPause ) {
			ALC_CALL( alcSuspendContext( _pContext ) );
			_bPause = true;
		}
	}

	inline void ALSoundSystem::Resume()
	{
		if ( !_bPause ) {
			ALC_CALL( alcProcessContext( _pContext ) );
			_bPause = false;
		}
	}

//-------------------------------------------------------------------

}	// ALShell
}	// UX_STL

#endif	// _UXS_AL_SOUND_SYSTEM_H